package com.ruicar.afs.cloud.bizcommon.rules.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.bizcommon.dto.rules.atom.AfsRuleAtomDto;
import com.ruicar.afs.cloud.bizcommon.rules.entity.AfsRuleAtom;
import com.ruicar.afs.cloud.bizcommon.rules.entity.AfsRuleAtomBusinessRel;
import com.ruicar.afs.cloud.bizcommon.rules.entity.AfsRuleAtomOperatorRel;
import com.ruicar.afs.cloud.bizcommon.rules.mapper.AfsRuleAtomMapper;
import com.ruicar.afs.cloud.bizcommon.rules.service.AfsRuleAtomBusinessRelService;
import com.ruicar.afs.cloud.bizcommon.rules.service.AfsRuleAtomOperatorRelService;
import com.ruicar.afs.cloud.bizcommon.rules.service.AfsRuleAtomService;
import com.ruicar.afs.cloud.bizcommon.vo.rules.AfsRuleAtomVo;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.query.QueryCondition;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;
import java.util.stream.Collectors;

/**
 * AfsRuleAtomServiceImpl
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date create on 2020-05-11 18:21:39
 * @since 1.0
 */
@Service
@Slf4j
@AllArgsConstructor
public class AfsRuleAtomServiceImpl extends ServiceImpl<AfsRuleAtomMapper, AfsRuleAtom> implements AfsRuleAtomService {
    /**
     * Afs atom business rel mapper
     * <p>Description: </p>
     */
    private final AfsRuleAtomBusinessRelService afsRuleAtomBusinessRelService;

    private final AfsRuleAtomOperatorRelService afsRuleAtomOperatorRelService;

    /**
     * Add rule atom boolean
     * <p>Description: </p>
     *
     * @param afsRuleAtomVo afs rule atom vo
     * @return the boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addRuleAtom(AfsRuleAtomVo afsRuleAtomVo) {
        testKey(afsRuleAtomVo);
        AfsRuleAtom afsRuleAtom = AfsRuleAtom.convertFromVo(afsRuleAtomVo);
        this.baseMapper.insert(afsRuleAtom);
        insetRelInfo(afsRuleAtomVo, afsRuleAtom);
        return Boolean.TRUE;
    }

    /**
     * Del rule atom boolean
     * <p>Description: </p>
     *
     * @param ruleAtomId afs rule atom dto
     * @return the boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delRuleAtom(Long ruleAtomId) {
        return this.baseMapper.deleteById(ruleAtomId)>0;
    }

    /**
     * Modify rule atom boolean
     * <p>Description: </p>
     *
     * @param afsRuleAtomVo afs rule atom vo
     * @return the boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean modifyRuleAtom(AfsRuleAtomVo afsRuleAtomVo) {
        testKey(afsRuleAtomVo);
        AfsRuleAtom dbAfsRuleAtom = this.baseMapper.selectById(Long.valueOf(afsRuleAtomVo.getId()));
        AfsRuleAtom afsRuleAtom = AfsRuleAtom.convertFromVo(afsRuleAtomVo);
        ;
        BeanUtil.copyProperties(afsRuleAtom, dbAfsRuleAtom, "createBy", "createTime", "id");
        this.baseMapper.updateById(dbAfsRuleAtom);

        afsRuleAtomBusinessRelService.remove(Wrappers.<AfsRuleAtomBusinessRel>lambdaQuery().eq(AfsRuleAtomBusinessRel::getAtomId, dbAfsRuleAtom.getId()));
        afsRuleAtomOperatorRelService.remove(Wrappers.<AfsRuleAtomOperatorRel>lambdaQuery().eq(AfsRuleAtomOperatorRel::getAtomId, dbAfsRuleAtom.getId()));
        insetRelInfo(afsRuleAtomVo, dbAfsRuleAtom);
        return Boolean.TRUE;
    }

    /**
     * Query response
     * <p>Description: </p>
     *
     * @param queryCondition query condition
     * @return the response
     */
    @Override
    public IResponse query(QueryCondition<AfsRuleAtomVo> queryCondition) {
        if (StringUtils.isNotEmpty(queryCondition.getCondition().getAtomName())) {
            queryCondition.getCondition().setAtomName("%" + queryCondition.getCondition().getAtomName() + "%");
        }
        if (queryCondition.getCondition().getRelList() != null && queryCondition.getCondition().getRelList().size() == 0) {
            queryCondition.getCondition().setRelList(null);
        }
        return IResponse.success(this.baseMapper.queryAtoms(new Page(queryCondition.getPageNumber(), queryCondition.getPageSize()), queryCondition.getCondition()));
    }

    @Override
    public IResponse<List<AfsRuleAtomDto>> queryAtomsByBizType(String bizType) {
        return IResponse.success(this.baseMapper.queryAtomsByBizType(bizType)
                .stream().map(afsRuleAtomVo -> {
                    AfsRuleAtomDto afsRuleAtomDto = new AfsRuleAtomDto();
                    afsRuleAtomDto.setKey(afsRuleAtomVo.getAtomKey());
                    afsRuleAtomDto.setName(afsRuleAtomVo.getAtomName());
                    afsRuleAtomDto.setValueExpress(afsRuleAtomVo.getAtomValueExpress());
                    afsRuleAtomDto.setOperatorScope(AfsEnumUtil.key(afsRuleAtomVo.getAtomOperatorScope()));
                    afsRuleAtomDto.setOperatorTypes(afsRuleAtomVo.getOperatorKeyList());
                    afsRuleAtomDto.setComponent(AfsEnumUtil.key(afsRuleAtomVo.getAtomType()));
                    afsRuleAtomDto.setComponentConfig(JSONObject.parseObject(afsRuleAtomVo.getAtomComponentConfig()));
                    return afsRuleAtomDto;
                }).collect(Collectors.toList()));
    }

    /**
     * Test key *
     *
     * @param afsRuleAtomVo afsRuleAtomVo
     */
    private void testKey(AfsRuleAtomVo afsRuleAtomVo) {
        long count = this.baseMapper.selectCount(Wrappers.<AfsRuleAtom>lambdaQuery()
                .eq(AfsRuleAtom::getAtomKey, afsRuleAtomVo.getAtomKey()).ne(afsRuleAtomVo.getId() != null, AfsRuleAtom::getId, afsRuleAtomVo.getId()));
        Assert.isTrue(count < 1, "原子key[" + afsRuleAtomVo.getAtomKey() + "]重复");

        long count1 = this.baseMapper.selectCount(Wrappers.<AfsRuleAtom>lambdaQuery()
                .eq(AfsRuleAtom::getAtomName, afsRuleAtomVo.getAtomName()).ne(afsRuleAtomVo.getId() != null, AfsRuleAtom::getId, afsRuleAtomVo.getId()));
        Assert.isTrue(count1 < 1, "原子中文名[" + afsRuleAtomVo.getAtomName() + "]重复");

        long count2 = this.baseMapper.selectCount(Wrappers.<AfsRuleAtom>lambdaQuery()
                .eq(AfsRuleAtom::getAtomValueExpress, afsRuleAtomVo.getAtomValueExpress()).ne(afsRuleAtomVo.getId() != null, AfsRuleAtom::getId, afsRuleAtomVo.getId()));
        Assert.isTrue(count2 < 1, "取值表达式[" + afsRuleAtomVo.getAtomValueExpress() + "]重复");
    }

    /**
     * Inset rel info *
     *
     * @param afsRuleAtomVo afs rule atom vo
     * @param afsRuleAtom   afs rule atom
     */
    private void insetRelInfo(AfsRuleAtomVo afsRuleAtomVo, AfsRuleAtom afsRuleAtom) {
        if (afsRuleAtomVo.getRelList() != null) {
            afsRuleAtomVo.getRelList().forEach(dicValue -> {
                AfsRuleAtomBusinessRel afsRuleAtomBusinessRel = new AfsRuleAtomBusinessRel();
                afsRuleAtomBusinessRel.setAtomId(afsRuleAtom.getId());
                afsRuleAtomBusinessRel.setBusinessDicValue(dicValue);
                afsRuleAtomBusinessRelService.save(afsRuleAtomBusinessRel);
            });
        }
        if (afsRuleAtomVo.getOperatorKeyList() != null) {
            afsRuleAtomVo.getOperatorKeyList().forEach(operatorKey -> {
                AfsRuleAtomOperatorRel afsRuleAtomOperatorRel = new AfsRuleAtomOperatorRel();
                afsRuleAtomOperatorRel.setAtomId(afsRuleAtom.getId());
                afsRuleAtomOperatorRel.setOperatorKey(operatorKey);
                afsRuleAtomOperatorRelService.save(afsRuleAtomOperatorRel);
            });
        }
    }
}
